package com.idealighter.game.games.fruitslot.common;

import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Table;

import com.idealighter.game.dictionary.dic.FruitslotBacketRewardDic;
import com.idealighter.game.dictionary.dic.FruitslotIconRewardDic;
import com.idealighter.game.dictionary.dic.FruitslotLineCoordDic;
import com.idealighter.game.dictionary.dic.FruitslotLineCoordDic.Coordinate;
import com.idealighter.game.dictionary.domain.FruitslotBasketRewardDomain;
import com.idealighter.game.dictionary.domain.FruitslotBonusNumCfgDomain;
import com.idealighter.game.games.fruitslot.dto.LineRewardIcons;
import com.idealighter.game.games.fruitslot.manager.FruitslotControlScript;
import com.idealighter.game.games.fruitslot.struct.FruistlotBasket;
import com.idealighter.game.server.context.ApplicationContext;
import com.idealighter.utils.check.EmptyUtil;
import com.idealighter.utils.code.RandCodeUtil;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;



public class RewardCalculator {

  // wild id
  private static final int WILD = 1;
  // 橘子 id
  private static final int BONUS = 2;
  // 木瓜 id
  private static final int PAWPAW = 11;
  // 木瓜数量
  // private static final int PAWPAW_TIMES = 3;


  private static final int SGL_MULTIPLE_NUM = 3;



  private RewardCalculator() {}

  /**
   * 根据图标和押注计算水果拉霸奖励.
   * 
   * @param icons 图标
   * @param line 压的线数
   * @param bet 每条线押注
   * @return 奖励
   */
  public static FruitslotReward calculate(Table<Integer, Integer, Integer> icons,
      Map<Integer, FruitslotBonusNumCfgDomain> bonusNumCfgMap, int line, long bet) {
    // 赢的筹码
    long win = 0;

    // 奖励类型(0:普通连线奖励 ,1.水果篮奖励)
    FruitslotRewardType type = FruitslotRewardType.COMMON_REWARD;
    // 线路奖励图标列表
    List<LineRewardIcons> lineRewardIconsList = new ArrayList<>();


    FruitslotLineCoordDic lineCoordDic = ApplicationContext.getBean(FruitslotLineCoordDic.class);

    // 先计算是否有3个木瓜

    // 倍数数组.
    List<FruistlotBasket> lotteryRewards = null;
    int pawpawTimes = 0;
    for (Integer icon : icons.values()) {
      if (icon == PAWPAW) {
        pawpawTimes++;
      }
    }
    if (pawpawTimes > 0) {
      lotteryRewards = randomMultiples(pawpawTimes);
      if (EmptyUtil.listIsNotEmpty(lotteryRewards)) {
        type = FruitslotRewardType.LOTTERY_REWARD;
      }
    }

    // 再计算bonus次数
    List<Boolean> bonusCheck = Lists.newArrayList(false, false, false, false, false);
    for (int col = 0; col < FruitslotControlScript.ICON_COLUMNS; col++) {
      for (int row = 0; row < FruitslotControlScript.ICON_ROWS; row++) {
        if (icons.get(row, col) == BONUS) {
          bonusCheck.set(col, true);
          break;
        }
      }
    }
    // 小玛丽次数
    int bonus = calBonusNumByColumn(bonusCheck, bonusNumCfgMap);


    /*
     * 再计算普通线路奖励和bonus次数 .
     */

    for (int row = 1; row <= line; row++) {
      // 每条线的 图标坐标
      List<Coordinate> lineCoordinates = lineCoordDic.coordinates.get(row);
      // 每条线的 图标,可重复有序map
      LinkedListMultimap<Integer, Integer> lineIconsMap = LinkedListMultimap.create();

      for (Coordinate coordinate : lineCoordinates) {
        Integer icon = icons.get(coordinate.row, coordinate.column);
        lineIconsMap.put(icon, icon);
      }

      // 该线全是wild 无作用
      // if (lineIconsMap.keySet().size() == 1 && lineIconsMap.keySet().contains(WILD)) {
      // LineRewardIcons destLineRewardIcons = new LineRewardIcons();
      // destLineRewardIcons.setLine(row);
      // destLineRewardIcons.setIcon(WILD);
      // Collections.addAll(destLineRewardIcons.getIndexs(), 0, 1, 2, 3, 4);
      // lineRewardIconsList.add(destLineRewardIcons);
      //
      // bonus += bonusNumCfgMap.get(5).getBonusNum();
      // int multiple = fruitslotIconRewardDic.map().get(WILD).getFiveLine();
      // win += bet * multiple;
      // continue;
      // }

      // 该线有至少一个但不全是wild,需要将wild替换进行计算
      if (lineIconsMap.keySet().contains(WILD)) {
        // 水果拉霸线路中奖图标信息
        LineRewardIcons destLineRewardIcons = new LineRewardIcons();
        destLineRewardIcons.setLine(row);


        // wild替换的最大倍数，eg:2,9,1,1,1
        int maxMultiple = 0;
        // 把wild替换进行计算
        for (Integer lineIcon : lineIconsMap.keySet()) {
          if (lineIcon != WILD && lineIcon != PAWPAW && lineIcon != BONUS) {
            // 线路图标
            ArrayList<Integer> lineIcons = new ArrayList<>(lineIconsMap.values());

            Collections.replaceAll(lineIcons, WILD, lineIcon);

            // 1-31 修改
            // 先计算bonus(去掉)
            // bonus 不计算连线
            // bonus += calBonusNum(lineIcons, bonusNumCfgMap);

            // 线路中奖图标位置
            ArrayList<Integer> rewardIconIndexs = new ArrayList<>(5);
            // 再计算倍数
            int multiple = calMultiple(lineIcons, rewardIconIndexs);

            // 判断最大倍数
            if (multiple > maxMultiple) {
              maxMultiple = multiple;
              destLineRewardIcons.setIndexs(rewardIconIndexs);
              destLineRewardIcons.setIcon(lineIcons.get(rewardIconIndexs.get(0)));
            }
          }
        }

        if (maxMultiple > 0) {
          win += bet * maxMultiple;
          lineRewardIconsList.add(destLineRewardIcons);
          continue;
        }
      }

      // 该线没有wild
      if (!lineIconsMap.keySet().contains(WILD)) {
        LineRewardIcons destLineRewardIcons = new LineRewardIcons();
        destLineRewardIcons.setLine(row);

        ArrayList<Integer> lineIcons = new ArrayList<>(lineIconsMap.values());

        // 1-31 修改
        // 先计算bonus(去掉)
        // bonus 不计算连线
        // bonus += calBonusNum(lineIcons, bonusNumCfgMap);
        // 线路中奖图标位置
        ArrayList<Integer> rewardIconIndexs = new ArrayList<>(5);

        // 再计算倍数
        int multiple = calMultiple(lineIcons, rewardIconIndexs);
        if (multiple > 0) {
          win += bet * multiple;
          destLineRewardIcons.setIndexs(rewardIconIndexs);
          destLineRewardIcons.setIcon(lineIconsMap.values().get(rewardIconIndexs.get(0)));
          lineRewardIconsList.add(destLineRewardIcons);
        }
      }
    }



    return new FruitslotReward(win, bonus, type.getType(), lineRewardIconsList, lotteryRewards);
  }

  /**
   * 木瓜数量获取水果篮.
   * 
   * @param pawpawTimes 木瓜出现次数.
   * @return 水果篮列表,不空and size >0 则表示有水果篮奖励.
   */
  private static List<FruistlotBasket> randomMultiples(int pawpawTimes) {
    FruitslotBacketRewardDic fruitslotBacketRewardDic =
        ApplicationContext.getBean(FruitslotBacketRewardDic.class);

    FruitslotBasketRewardDomain basketRewardDomain = fruitslotBacketRewardDic.get(pawpawTimes);

    List<FruistlotBasket> multiples = new ArrayList<>();
    if (basketRewardDomain != null) {
      for (int i = 0; i < SGL_MULTIPLE_NUM; i++) {
        Integer multiple = RandCodeUtil.random(basketRewardDomain.getMinMultiple(),
            basketRewardDomain.getMaxMultiple());
        FruistlotBasket basket = new FruistlotBasket();
        basket.setMultiple(multiple);
        basket.setRate(basketRewardDomain.getRate());
        multiples.add(basket);
      }
    }



    return multiples;
  }

  /**
   * 计算线路的5个图标的倍数,只算左边.
   * 
   * @param lineIcons 线路的图标(没有wild)
   * @param rewardIconIndexs 中奖的图标
   * @return 赔率
   */
  private static int calMultiple(List<Integer> lineIcons, List<Integer> rewardIconIndexs) {
    int multiple = 0;
    // 左边第一个
    int leftFirst = lineIcons.get(0);

    // icon 为 wild 或者 bonus 或者 木瓜都不计算倍数
    if (leftFirst != WILD && leftFirst != BONUS && leftFirst != PAWPAW) {
      // 左边连着的个数
      int leftNum = 1;
      for (int i = 1; i < lineIcons.size(); i++) {
        if (lineIcons.get(i) == leftFirst) {
          leftNum++;
        } else {
          break;
        }
      }

      multiple = getIconMultiple(leftFirst, leftNum);

      if (multiple > 0) {
        for (int i = 0; i < leftNum; i++) {
          rewardIconIndexs.add(i);
        }
      }
    }
    return multiple;

  }

  /**
   * 计算Bonus游戏次数, . 3/4/5个连着的才有.
   * 
   * @param lineIcons 连线 .
   * @return bonus数量.
   */
  private static int calBonusNumByColumn(List<Boolean> colContains,
      Map<Integer, FruitslotBonusNumCfgDomain> bonusNumCfgMap) {
    int bonusNum = 0;

    int maxColumn = maxBonusColumn(colContains);

    if (maxColumn > 2) {
      bonusNum = bonusNumCfgMap.get(maxColumn).getBonusNum();
    }
    return bonusNum;
  }

  /**
   * 计算最大bonus . 列数.
   * 
   * @param colContains bonus列表.
   * @return 最大列数.
   */
  private static int maxBonusColumn(List<Boolean> colContains) {
    int maxColumn = 0;
    for (int index = 0; index < colContains.size(); index++) {
      int tempMax = 0;
      for (int countIndex = index; countIndex < colContains.size(); countIndex++) {
        if (colContains.get(countIndex)) {
          tempMax++;
        } else {
          break;
        }
      }
      if (tempMax > maxColumn) {
        maxColumn = tempMax;
      }
    }
    return maxColumn;
  }

  /**
   * 获取图标的中奖倍数.
   * 
   * @param icon 图标
   * @param num 数量
   * @return 赔率
   */
  private static int getIconMultiple(int icon, int num) {
    int multiple = 0;
    FruitslotIconRewardDic fruitslotIconRewardDic =
        ApplicationContext.getBean(FruitslotIconRewardDic.class);
    switch (num) { // 至少连着2个
      case 2:
        multiple = fruitslotIconRewardDic.map().get(icon).getTwoLine();
        break;
      case 3:
        multiple = fruitslotIconRewardDic.map().get(icon).getThreeLine();
        break;
      case 4:
        multiple = fruitslotIconRewardDic.map().get(icon).getFourLine();
        break;
      case 5:
        multiple = fruitslotIconRewardDic.map().get(icon).getFiveLine();
        break;
      default:
        break;
    }

    return multiple;
  }
}
